﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml;

namespace Cn.Edwon.Web.Crud {
    public class HbmReader {
        public static ModelEO Parse(String typeName) {
            Type t = Type.GetType(typeName);
            return Parse(t);
        }
        private static String FindResource(Type t) {
            String eoName = t.Name;
            Assembly assem = t.Assembly;
            String assemName = assem.GetName().Name;
            String[] res = assem.GetManifestResourceNames();
            for (int i = 0; i < res.Length; i++) {
                if (res[i].ToLower().IndexOf(eoName.ToLower() + ".hbm.xml") != -1) {
                    return res[i];
                }
            }
            return null;
        }
        public static ModelEO Parse(Type t) {
            ModelEO model = new ModelEO();
            model.Type = t;
            String resource = FindResource(t);
            if (resource == null) {
                throw new Exception("nhibernate configuration-file for " + t.Name + " was not found!");
            }
            Stream xmlStream = t.Assembly.GetManifestResourceStream(resource);
            XmlDocument doc = new XmlDocument();
            XmlNamespaceManager xnm = new XmlNamespaceManager(new NameTable());
            xnm.AddNamespace("nh", "urn:nhibernate-mapping-2.2");
            doc.Load(xmlStream);
            XmlNode nid = doc.SelectSingleNode("//nh:class/nh:id", xnm);
            model.Pk = nid.Attributes["name"].Value;
            XmlNodeList nodes = doc.SelectNodes("//nh:class/nh:property", xnm);
            model.Properties = new List<PropertyEO>();
            foreach (XmlNode node in nodes) {
                model.Properties.Add(Parse(node));
            }
            XmlNodeList nodes2 = doc.SelectNodes("//nh:class/nh:many-to-one", xnm);
            foreach (XmlNode node in nodes2) {
                model.Properties.Add(ParseMany21(node));
            }
            return model;
        }
        public static PropertyEO ParseMany21(XmlNode node) {
            if (node == null) return null;
            PropertyEO eo = new PropertyEO();
            eo.Name = node.Attributes["name"].Value;
            eo.Length = 0;
            eo.Unique = false;
            eo.DataType = "select";
            if (node.Attributes["not-null"] != null)
                eo.NotNull = ((node.Attributes["not-null"].Value == "true")
                      || (node.Attributes["not-null"].Value == "1"));
            else
                eo.NotNull = false;
            if (node.Attributes["class"] != null) {
                String[] t = node.Attributes["class"].Value.Replace(" ", "").Split(',');
                if (t.Length > 1) {
                    eo.DataSource = new DataSourceEO();
                    eo.DataSource.DataType = eo.Type = Assembly.Load(t[1]).GetType(t[0]);
                    eo.DataSource.TxtColumn = "Name";
                    eo.DataSource.ValColumn = "ID";
                }
            }
            return eo;
        }
        public static PropertyEO Parse(XmlNode node) {
            if (node == null) return null;
            PropertyEO eo = new PropertyEO();
            eo.Name = node.Attributes["name"].Value;
            if (node.Attributes["not-null"] != null)
                eo.NotNull = ((node.Attributes["not-null"].Value == "true")
                      || (node.Attributes["not-null"].Value == "1"));
            else
                eo.NotNull = false;

            try {
                eo.Type = Type.GetType(node.Attributes["type"].Value);
                if (eo.Type == null) eo.Type = typeof(String);
            } catch {
                eo.Type = typeof(String);
            }

            try {
                eo.Length = Convert.ToInt32(node.Attributes["length"].Value);
            } catch {
                eo.Length = 0;
            }

            if (node.Attributes["unique"] != null)
                eo.Unique = ((node.Attributes["unique"].Value == "true")
                    || (node.Attributes["unique"].Value == "1"));
            else
                eo.Unique = false; 

            return eo;
        }
    
    }
}
